package generic;

import java.util.ArrayList;
import java.util.Stack;

/**
 * Created with IDEA
 * author:ju bai
 * Date:2021/2/21
 * Time:11:19
 **/



/**
 * Object是所有类的父类
 * 泛型：
 * 1.class MyStack<T>
 */
class MyStack<T>{
    public T[] elem;
    public int top;

    public MyStack(){
        this.elem = (T[]) new Object[10];
    }
    public void push(T val){
        this.elem[top] = val;
        top++;
    }
    public T getTop(){
        return this.elem[top-1];
    }
}


/**
 * 写一个泛型类，找到数组当中的最大值
 * 泛型的上界：
 * class Algorithm <T extends Comparable<T>>
 *     T:T类型 一定要实现comparable接口
 * class Algorithm <E extends animal>
 *     E:可以是animal的子类或animal自己类本身
 * 泛型无下界
 */

class Algorithm <T extends Comparable<T>> {

    public T findMaxVal(T[] array){
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) >= 0){
                max = array[i];
            }
        }
        return max;
    }
}

/**
 * 泛型方法
 */
class Algorithm2  {

    public static<T extends Comparable<T>> T findMaxVal(T[] array){
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) >= 0){
                max = array[i];
            }
        }
        return max;
    }
}

/**
 * 写一个泛型方法，打印一个list当中所有的数据
 *
 * 通配符：？
 * 实际上也是一种泛型，一般用在源码之中居多
 * 使用层面上：通配符一般用于读取
 *           泛型一般用于读取和写入
 *
 * 通配符的
 * 上界：<? extends E> 表示传入的参数？是下界 E的子类或 E自己本身
 * 下界：<? super E> 表示传入的参数？是下界 E的父类或 E自己本身
 *
 * 泛型中的父子类型:
 *
 * MyArrayList<Object> 不是 MyArrayList<Number> 的父类型
 * MyArrayList<Number> 也不是 MyArrayList<Integer> 的父类型
 * 需要使用通配符来确定父子类型:
 *
 * MyArrayList<?> 是 MyArrayList<? extends Number> 的父类型
 * MyArrayList<? extends Number> 是 MyArrayList<Integer> 的父类型
 */
class Test{
    public static void print2(ArrayList<?> list){
        for (Object x:list) {
            System.out.print(x+" ");
        }
    }
    public static<T> void print(ArrayList<T> list){
        for (T x:list) {
            System.out.print(x+" ");
        }
    }
}

public class TestDemo1 {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        Test.print(list1);

        ArrayList<Double> list2 = new ArrayList<>();
        list2.add(1.0);
        list2.add(2.0);
        list2.add(3.0);
        list2.add(4.0);
        Test.print(list2);
    }
    public static void main4(String[] args) {
        Integer[] array = {1,2,3,4,5,6,7,8};//不用new对象
        System.out.println(Algorithm2.findMaxVal(array));
        System.out.println(Algorithm2.<Integer>findMaxVal(array));
    }
    public static void main3(String[] args) {
        Algorithm<Integer> algorithm = new Algorithm<>();
        Integer[] array = {1,2,3,4,5,6,7,8};
        System.out.println(algorithm.findMaxVal(array));
    }
    public static void main2(String[] args) {
        MyStack<Integer> myStack = new MyStack<>();
        System.out.println(myStack);
    }
    public static void main1(String[] args) {
        /*Stack<Integer> stack1 = new Stack<>();
        Stack<String> stack2 = new Stack<>();
        Stack<Double> stack3 = new Stack<>();*/

        /*MyStack myStack = new MyStack();

        myStack.push(1);
        myStack.push(1.0);
        myStack.push("jubai");

        String str = (String)myStack.getTop();//此时不知道是什么类型的，需要强制类型转换
        System.out.println(str);*/

        MyStack<Integer> myStack1 = new MyStack<>();

        myStack1.push(1);
        myStack1.push(2);
        myStack1.push(3);

        int a = myStack1.getTop();
        System.out.println(a);

        MyStack<String> myStack2 = new MyStack<>();

        myStack2.push("qwe");
        myStack2.push("rty");
        myStack2.push("uio");

        String b = myStack2.getTop();
        System.out.println(b);

    }
}
